package com.swyc.osschat.Test.designMode.factory.run;

import com.swyc.osschat.Test.designMode.factory.base.ACar;
import com.swyc.osschat.Test.designMode.factory.base.BCar;
import com.swyc.osschat.Test.designMode.factory.base.Car;
import com.swyc.osschat.Test.designMode.factory.fac.CarFactory;
import com.swyc.osschat.Test.designMode.factory.impl.BoraFactory;
import com.swyc.osschat.Test.designMode.factory.impl.ShangQiFactory;
import com.swyc.osschat.Test.designMode.factory.impl.YiQiFactory;

/**
 * @description Java 工厂模式
 * 一、简介
 *  工厂模式为创建型模式，在创建对象时，不会向客户端暴露对象的创建逻辑，通过使用一个共同的接口或抽象类来指向新创建的对象。
 *  在日常开发中，工厂模式分为三种：简单工厂模式、工厂方法模式、抽象工厂模式。
 * 二、简单工厂模式
 *  简单工厂模式又称静态工厂方法模式，由一个专门的工厂类来创建具体的实例。作用是将类的实例化与使用者分开，使用者不需要关心类是如何创建的，在一定程度上实现了解耦。
 *  主要角色：
 *      工厂： 负责创建所需实例，提供一个供外部使用的方法来获取具体产品。
 *      抽象产品：负责描述产品的抽象类或接口。
 *      具体产品：我们所需要的具体产品（类实例）
 * @Author: z156940l@outlook.com
 * @className Test
 * @Date: 2022/7/25 22:26
 */
public class Test {
    public static void main(String[] args) {
        test1();
        test2();
        test3();
        test4();
    }

    /**
     * 比如有 一汽大众汽车厂（工厂），可以生产不同类型的汽车（抽象产品），比如宝来和速腾（具体产品），这时候可以通过汽车厂来获取想要的具体车型。
     * 这样一个简单工厂模式就完成了，简单理解就是说工厂类通过抽象产品类来创建出具体的产品，调用者无需知道具体产品是如何创建出来的。
     * 优点：类的使用和创建分开，在一定程度上解耦。
     * 缺点：当需要添加一个产品时，还需要修改工厂类，违反开闭原则。
     */
    private static void test1(){
        Car car = CarFactory.getCar("bora");
        System.out.println(car.carInfo());
    }

    /**
     * 工厂方法模式
     * 工厂方法模式相比上面的简单工厂多了抽象工厂，将产品的创建延迟到抽象工厂的子类（具体工厂）。
     * 主要角色：
     *      抽象工厂： 提供创建产品的接口，由子类（具体工厂）来创建具体的产品。
     *      具体工厂：实现抽象工厂的方法，来创建具体产品。
     *      抽象产品：负责描述产品的抽象类或接口。
     *      具体产品：我们所需要的具体产品（类实例）
     * 举例：
     * 比如有 一汽大众汽车厂（抽象工厂），他有两个生产线，宝来生产线（具体工厂）和速腾生产线（具体工厂），通过这两个生产线来生产具体的产品（宝来，速腾）。
     * 工厂方法模式比简单工厂模式的优点就是符合开闭原则，如果新增一款产品，只需要创建新的具体工厂即可，缺点是：
     * 一个具体工厂只能创建一个具体产品，每增加一款产品都要新增一个类，导致类爆炸。
     */
    private static void test2(){
        CarFactory boraFactory = new BoraFactory();
        //通过具体工厂获取实例
        Car car = boraFactory.getCar();
        System.out.println(car.carInfo());
    }

    /**
     * 抽象工厂模式
     * 是一种为访问类提供一个 创建一组相关 或 相互依赖对象的接口，且访问类无须指定所要产品的具体类就能得到同产品不同等级的产品的结构。
     * 抽象工厂模式是工厂方法的升级版本，工厂方法只能生产同一种等级的产品，而抽象工厂模式可以生产多个等级的产品。
     * 主要角色：
     *      抽象工厂： 提供创建产品的接口，包含多个创建产品的方法，可以创建多个不同等级的产品。
     *      具体工厂：实现抽象工厂多个抽象方法，来创建具体产品。
     *      抽象产品：负责描述产品的抽象类或接口。
     *      具体产品：我们所需要的具体产品（类实例）
     * 举例：
     *  我们有一个总的汽车厂（抽象工厂），通过它生产A级车和B级车。同时还有一汽大众和上汽大众（具体工厂）来创建具体的产品，比如一起大众有A级车宝来，
     *  B级别车迈腾，上汽大众有A级车朗逸，B级车帕萨特，所以我们需要如下几个类。
     * 比如说我们看车的时候想看一汽大众的A级车或者B级车。
     * 抽象工厂类（车厂）衍生出多个具体工厂（一汽/上汽）。多个抽象产品类(A/B级车)，衍生出多个具体产品，宝来朗逸迈腾帕萨特。
     * 再通过具体工厂创建多个界别的产品，通过上面的例子我们可以理解为：抽象工厂模式就是创建同一个品牌，不同级别的产品。
     * 优点：低耦合，符合开闭原则，单一职责原则，
     * 缺点：不易扩展，当新增了一个新的产品时，工厂类也需要进行修改。
     */
    private static void test3(){
        //获取一汽大众工厂
        YiQiFactory yiQiFactory = new YiQiFactory();
        //获取一汽大众的A级车和B级车
        ACar aCar = yiQiFactory.createACar();
        BCar bCar = yiQiFactory.createBCar();
        System.out.println(aCar.carInfo());
        System.out.println(bCar.carInfo());
    }

    /**
     * 又比如我想去上汽大众看看。
     */
    private static void test4(){
        //获取上汽大众工厂
        ShangQiFactory shangQiFactory = new ShangQiFactory();
        //获取上汽大众的A级车和B级车
        ACar aCar = shangQiFactory.createACar();
        BCar bCar = shangQiFactory.createBCar();
        System.out.println(aCar.carInfo());
        System.out.println(bCar.carInfo());
    }
}
